// 引用文件
import {
  Cache,
  Scene,
  PerspectiveCamera,
  WebGLRenderer,
  Color,
  sRGBEncoding,
  AmbientLight,
  PointLight
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { EventDispatcher } from 'three';
import Stats from 'three/examples/jsm/libs/stats.module';

class Index extends EventDispatcher {
  constructor(el, viewOption = {}, lightOption = {}) {
    super();
    this.el = el;
    this.renderer = undefined;
    this.scene = undefined;
    this.camera = undefined;
    this.controls = undefined;
    this.normalScene = undefined;
    this.css3dScene = undefined;
    this.statsControls = undefined;
    this.labelRenderer = undefined;
    this.css3DRenderer = undefined;
    this.animateEventList = [];
    this.viewOption = viewOption;
    this.lightOption = lightOption;

    this._initViewer();
  }

  beforeDestroy() {
    this.scene.traverse(child => {
      if (child.material) {
        child.material.dispose();
      }
      if (child.geometry) {
        child.geometry.dispose();
      }
      child = null;
    });
    this.renderer.forceContextLoss();
    this.renderer.dispose();
    this.scene.clear();
  }

  _initViewer() {
    this._initRenderer(); // 默认自动初始化
    this._initCamera();
    this._initScene();
    // this.initLight(); // 默认自动初始化
    // this.customInit(); // 用户自定义初始化
    this._initControls(); // 默认自动初始化
    this._initStats(); // 默认自动初始化

    // 全局调试器
    const that = this;

    function animate() {
      requestAnimationFrame(animate);
      that._updateDom();
      that._readerDom();
      // 全局的公共动画函数，添加函数可同步执行
      if (that.animateEventList.length) {
        that.animateEventList.forEach(event => {
          event.fun && event.content && event.fun(event.content);
        });
      }
    }

    animate();
  }

  // 初始化三大件：场景、相机、渲染器
  _initRenderer() {
    let { rendererOption } = this.viewOption;

    let option = {
      logarithmicDepthBuffer: true,
      antialias: true, // true/false表示是否开启反锯齿
      alpha: true, // true/false 表示是否可以设置背景色透明
      precision: 'mediump', // highp/mediump/lowp 表示着色精度选择
      premultipliedAlpha: true, // true/false 表示是否可以设置像素深度（用来度量图像的分辨率）
      // preserveDrawingBuffer: false, // true/false 表示是否保存绘图缓冲
      physicallyCorrectLights: true // true/false 表示是否开启物理光照
    };
    rendererOption = Object.assign(option, rendererOption);

    this.renderer = new WebGLRenderer(rendererOption);
    this.renderer.clearDepth();
    // this.renderer.domElement.style.zIndex = 1
    // 默认情况下，js的光强数值不真实。为了使得光强更趋于真实值，应该把渲染器的physicallyCorrectLights属性设为true
    // this.renderer.physicallyCorrectLights = true
    // this.renderer.toneMapping = ACESFilmicToneMapping // 尽管我们的贴图不是HDR，但使用tone mapping可以塑造更真实的效果。
    // this.renderer.toneMappingExposure = 4 // tone mapping的曝光度
    this.renderer.shadowMap.enabled = true; // 场景中的阴影自动更新
    // this.renderer.shadowMap.type = PCFSoftShadowMap // 设置渲染器开启阴影贴图，并将类型设为PCFSoftShadowMap
    this.renderer.outputEncoding = sRGBEncoding; // 这下我们可以看到更亮的材质，同时这也影响到环境贴图。

    this.el.appendChild(this.renderer.domElement);
  }

  _initCamera() {
    // 渲染相机
    const { cameraOption } = this.viewOption;
    if (cameraOption && Array.isArray(cameraOption)) {
      this.camera = new PerspectiveCamera(...cameraOption);
    } else {
      this.camera = new PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
    }

    this.camera.position.set(50, 0, 50);
    this.camera.lookAt(0, 0, 0);
  }

  _initScene() {
    // 渲染场景
    this.scene = new Scene();
    this.css3dScene = new Scene();
    this.scene.background = new Color('rgb(5,24,38)');
  }

  // 设置灯光
  initLight(lightOption = 0xffffff) {
    this.ambientLight = new AmbientLight(lightOption); // 自然光，每个几何体的每个面都有光
    this.scene.add(this.ambientLight);
  }

  customInit() {
    this.normalScene = new Scene(); // 增添一个新的场景用来做部分辉光效果
    this.scene.background = new Color('rgb(25, 35, 39)');
    this.camera.position.set(-20, 40, 90);
    this.renderer.setSize(this.el.clientWidth, this.el.clientHeight);
    this.renderer.autoClear = false; // 要使用高级效果组合器MaskPass，必须设置为false
    this.pointLight = new PointLight(0xff0000, 10); // 点光源
    this.pointLight.position.set(0, 50, 0);
    this.scene.add(this.pointLight);
  }

  // 添加控制器
  _initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    this.controls.enableDamping = false;
    // this.controls.screenSpacePanning = false // 定义平移时如何平移相机的位置 控制不上下移动
  }

  // 更新dom大小
  _updateDom() {
    const that = this;
    that.controls.update();
    that.stats.update();

    // 更新参数
    that.camera.aspect = that.el.clientWidth / that.el.clientHeight; // 摄像机视锥体的长宽比，通常是使用画布的宽/画布的高
    that.camera.updateProjectionMatrix(); // 更新摄像机投影矩阵。在任何参数被改变以后必须被调用,来使得这些改变生效
    that.renderer.setSize(that.el.clientWidth, that.el.clientHeight);
    that.renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比
    // that.labelRenderer.setSize(
    //   that.el.clientWidth,
    //   that.el.clientHeight
    // );
    // that.css3DRenderer.setSize(
    //   that.el.clientWidth,
    //   that.el.clientHeight
    // );
  }

  _readerDom() {
    this.renderer.render(this.scene, this.camera);
    // this.labelRenderer.render(this.scene, this.camera);
    // this.css3DRenderer.render(this.css3dScene, this.camera);
  }

  // 添加fps
  _initStats() {
    this.stats = new Stats();
    this.stats.domElement.style.position = 'absolute';
    this.el.parentNode.appendChild(this.stats.dom);
  }
}

export default Index;
